package com.ruizhong.centercontroll.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruizhong.centercontroll.dao.TScreenMapper;
import com.ruizhong.centercontroll.entity.THall;
import com.ruizhong.centercontroll.entity.TScreen;
import com.ruizhong.centercontroll.service.TScreenService;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

@Service
public class TScreenServiceImpl extends ServiceImpl<TScreenMapper, TScreen> implements TScreenService {

    private ThreadPoolExecutor executor = new ThreadPoolExecutor(
            9,
            10,
            1,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(500),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
    );


    @Override
    public synchronized void submitNewScreen(TScreen tScreen) {
        String exhibitionHall = tScreen.getExhibitionHall();
        List<TScreen> list = lambdaQuery()
                .eq(TScreen::getExhibitionHall, exhibitionHall)
                .list();
        Set<String> exhibitionHallName = list.stream().map(curScreen -> {
            return curScreen.getExhibitionHall() + "#" + curScreen.getExhibitionHallInTraditional() + "#" + curScreen.getExhibitionHallInEnglish();
        }).collect(Collectors.toSet());
        for (String s : exhibitionHallName) {
            String curExhibitionHallName = tScreen.getExhibitionHall() + "#" + tScreen.getExhibitionHallInTraditional() + "#" + tScreen.getExhibitionHallInEnglish();
            if (!curExhibitionHallName.equals(s)) {
                throw new RuntimeException("屏幕名称发生冲突");
            }
        }
        tScreen.setDefineIndex(0);
        save(tScreen);
    }

    @Override
    public Map<String, List<TScreen>> getAllScreenList() {
        List<TScreen> list = list();
        HashMap<String, List<TScreen>> resMap = new HashMap<>();
        for (TScreen screen : list) {
            String exhibitionHall = screen.getExhibitionHall();
//            String exhibitionHallInTraditional = screen.getExhibitionHallInTraditional();
//            String exhibitionHallInEnglish = screen.getExhibitionHallInEnglish();
            List<TScreen> tScreens = resMap.get(exhibitionHall);
            if (CollectionUtils.isEmpty(tScreens)) {
                tScreens = new ArrayList<>();
                resMap.put(exhibitionHall, tScreens);
            }
            tScreens.add(screen);
        }
        resMap.forEach(new BiConsumer<String, List<TScreen>>() {
            @Override
            public void accept(String s, List<TScreen> tScreens) {
                List<TScreen> collect = tScreens.stream().sorted(Comparator.comparing(TScreen::getDefineIndex)).collect(Collectors.toList());
                resMap.put(s, collect);
            }
        });
        return resMap;
    }

    @Override
    public TScreen getScreenDetailById(Integer id) {
        TScreen tScreen = lambdaQuery()
                .eq(TScreen::getId, id)
                .one();
        return tScreen;
    }

    @Override
    public synchronized void updateScreenInfo(TScreen tScreen) {
        String exhibitionHall = tScreen.getExhibitionHall();
        List<TScreen> list = lambdaQuery()
                .eq(TScreen::getExhibitionHall, exhibitionHall)
                .list();
        Set<String> exhibitionHallName = list.stream().map(curScreen -> {
            return curScreen.getExhibitionHall() + "#" + curScreen.getExhibitionHallInTraditional() + "#" + curScreen.getExhibitionHallInEnglish();
        }).collect(Collectors.toSet());
        for (String s : exhibitionHallName) {
            String curExhibitionHallName = tScreen.getExhibitionHall() + "#" + tScreen.getExhibitionHallInTraditional() + "#" + tScreen.getExhibitionHallInEnglish();
            if (!curExhibitionHallName.equals(s)) {
                throw new RuntimeException("屏幕名称发生冲突");
            }
        }
        updateById(tScreen);
    }

    @Override
    public List<THall> getAllHall() {
        List<TScreen> list = list();
        Set<THall> tHalls = list.stream().map(tScreen -> {
                    THall hallMap = new THall();
                    hallMap.setExhibitionHall(tScreen.getExhibitionHall());
                    hallMap.setExhibitionHallInTraditional(tScreen.getExhibitionHallInTraditional());
                    hallMap.setExhibitionHallInEnglish(tScreen.getExhibitionHallInEnglish());
                    hallMap.setDefineIndex(tScreen.getHallIndex() == null?0:tScreen.getHallIndex());
                    return hallMap;
                })
                .collect(Collectors.toSet());

        List<THall> halls = tHalls.stream()
                .sorted(Comparator.comparing(THall::getDefineIndex))
                .collect(Collectors.toList());
        return halls;
    }

    @Override
    public List<TScreen> getScreenListByHallName(String hallName) {
        List<TScreen> list = lambdaQuery()
                .eq(TScreen::getExhibitionHall, hallName)
                .or()
                .eq(TScreen::getExhibitionHallInTraditional, hallName)
                .or()
                .eq(TScreen::getExhibitionHallInEnglish, hallName)
                .list();
        return list;
    }

    @Override
    public void deleteScreenById(Integer id) {
        removeById(id);
    }

    @Override
    public void jumpByCueId(Integer sqId, Integer cueId, Boolean forAll, String ip) {
        if (!forAll) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    String url = "http://" + ip + ":45220/MOVETOCUE/" + sqId + "/" + cueId;
                    sendWithoutRes(url);
                }
            });
        } else {
            List<TScreen> list = list();
            for (int i = 0; i < list.size(); i++) {
                TScreen tScreen = list.get(i);
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        sendWithoutRes("http://" + ip + ":45220/MOVETOCUE/" + tScreen.getSequenceId() + "/" + cueId);
                    }
                });
            }
        }

    }

    private void sendWithoutRes(String url) {
        try {
            URL obj = new URL(url);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();
            System.out.println(url);
            // 设置请求方法、输出、输入
            con.setRequestMethod("GET");
            con.setRequestProperty("Content-Type", "application/json");
            con.setRequestProperty("Accept", "application/json");
            // 读取响应
//            int responseCode = con.getResponseCode();
//            System.out.println("Response Code : " + responseCode);
            // 注意：这里只是检查响应码，并没有读取响应体
            // 如果需要读取响应体，可以像GET请求那样使用BufferedReader
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            System.out.println(response);
            con.disconnect();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void changeMode(Integer sqId, String mode, Boolean forAll, String ip) {
        if (!forAll) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    String url = "http://" + ip + ":45220/PLAYMODE/" + sqId + "/" + mode;
                    sendWithoutRes(url);
                }
            });
        } else {
            List<TScreen> list = list();
            for (int i = 0; i < list.size(); i++) {
                TScreen tScreen = list.get(i);
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        sendWithoutRes("http://" + ip + ":45220/PLAYMODE/" + tScreen.getSequenceId() + "/" + mode);
                    }
                });
            }
        }

    }

    @Override
    public void nextLastCue(Integer sqId, Integer isNext, Boolean forAll, String ip) {
        if (!forAll) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    String url = "http://" + ip + ":45220/MOVETONEXTCUE/" + sqId + "/" + isNext;
                    sendWithoutRes(url);
                }
            });
        } else {
            List<TScreen> list = list();
            for (int i = 0; i < list.size(); i++) {
                TScreen tScreen = list.get(i);
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        sendWithoutRes("http://" + ip + ":45220/MOVETONEXTCUE/" + tScreen.getSequenceId() + "/" + isNext);
                    }
                });
            }
        }

    }

    @Override
    public void isFastForward(Integer sqId, Integer isNext, Boolean forAll, String ip) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                String url = "http://" + ip + ":45220/GETTIME/" + sqId;
                String res = sendWithRes(url);
                System.out.println(res);
                String[] timeArr = res.split(":");
                int hours = Integer.parseInt(timeArr[0]);
                int minutes = Integer.parseInt(timeArr[1]);
                int seconds = Integer.parseInt(timeArr[2]);

                int totalSeconds = hours * 3600 + minutes * 60 + seconds;
                // 增加或减少秒数
                totalSeconds += (isNext == 1 ? 5 : -5);
                // 转换回小时、分钟和秒
                hours = totalSeconds / 3600;
                minutes = (totalSeconds % 3600) / 60;
                seconds = totalSeconds % 60;
                if (!forAll) {
                    sendWithoutRes("http://" + ip + ":45220/MOVETOTIME/" + sqId + "/" + hours + "/" + minutes + "/" + seconds + "/" + 0);
                } else {
                    int finalHours = hours;
                    int finalMinutes = minutes;
                    int finalSeconds = seconds;
                    List<TScreen> list = list();
                    for (int i = 0; i < list.size(); i++) {
                        TScreen tScreen = list.get(i);

                        executor.execute(new Runnable() {
                            @Override
                            public void run() {
                                sendWithoutRes("http://" + ip + ":45220/MOVETOTIME/" + tScreen.getSequenceId() + "/" + finalHours + "/" + finalMinutes + "/" + finalSeconds + "/" + 0);
                            }
                        });
                    }
                }
            }
        });
    }

    @Override
    public void changeOrder(Map conditionMap) {
        String[] idsList = conditionMap.get("idList").toString().split(",");
        for (int i = 0; i < idsList.length; i++) {
            String s = idsList[i];
            lambdaUpdate()
                    .eq(TScreen::getId, Integer.parseInt(s))
                    .set(TScreen::getDefineIndex, i)
                    .update();
        }

    }

    @Override
    public void changeHallOrder(Map conditionMap) {
        String[] nameList = conditionMap.get("nameList").toString().split(",");
        for (int i = 0; i < nameList.length; i++) {
            String s = nameList[i];
            lambdaUpdate()
                    .eq(TScreen::getExhibitionHall, s)
                    .set(TScreen::getHallIndex, i)
                    .update();
        }

    }

    private String sendWithRes(String url) {
        try {
            URL obj = new URL(url);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();

            // 设置请求方法、输出、输入
            con.setRequestMethod("GET");
            con.setRequestProperty("Content-Type", "application/json");
            con.setRequestProperty("Accept", "application/json");
            // 读取响应
            int responseCode = con.getResponseCode();
            // 如果响应码是200（OK），那么可以读取响应体
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 读取响应体的内容
                InputStream inputStream = con.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                String line;
                StringBuilder response = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();
                con.disconnect();
                return response.toString();
            } else {
                // 响应码不是200，可以根据需要处理
                System.out.println("Response Code : " + responseCode);
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
